﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using SistemaCenterQuimPost.Plantillas; //necesario para obtener fecha, nombre usuario etc. Desde el formulario padre


using SistemaCenterQuimPost.Entidad;  //Usado para instanciar objetos de clase Producto y agilizar el filtrado de descripción.

using SistemaCenterQuimPost.Control; //Usado para validar textBox

namespace SistemaCenterQuimPost.UI.PostCajero
{
    public partial class frmAltaProductosDisueltos : SistemaCenterQuimPost.UI.frmGestionProductos
    {
        //------------ATRIBUTOS---------------
        
        
        //todos los metodos del padre, que usen resgProductoActual, deben ser obligadamente redefinido, ya que no procesarán sobre los mismos objetos. Acá es más reducido los datos que se almacenan
        new private string[] resgProductoActual; //al ser una interface polifuncional. Guarda el producto encontrado en una busqueda exitosa. {codigoBarra, descripcion}   


        //--------CONSTRUCTORES---------------
        
        public frmAltaProductosDisueltos()
        {
            InitializeComponent();

            this.resgProductoActual = new String[2];  //inicializamos el resgProductoActual

            removerControles();  //elimina los controles que no son necesarios.
            
        }

        //---------ESTADOS--------------------

        //redefinido del padre.
        protected override void estEsperandoOperacion() //estado inicial.
        {
            System.Windows.Forms.Control[] controlesHabilitados = { };
            System.Windows.Forms.Control[] controlesDeshabilitados = {lstProductosCodBarra, lstProductosDescripcion};
            System.Windows.Forms.Control[] controlesVisibles = { };
            System.Windows.Forms.Control[] controlesInvisibles = { lstProductosCodBarra, lstProductosDescripcion, lblError };

            habilitarControles(controlesHabilitados);
            deshabilitarControles(controlesDeshabilitados);
            visibleControles(controlesVisibles);
            invisibleControles(controlesInvisibles);

            if (refrescarResgProductos) //si hace falta actualizar el refrescarResgProducto se realiza
            {
                ejecutarHiloActualizarResgProductos();

            }

            this.txtCantidad.Text = ""; //vacia txtCantidad

            errorProvider1.Clear();  //se borran los errores, si habian.

            txtCodBarra.Focus();   //se deja el foco en txtCodBarra

            estadoDelFormulario = "estEsperandoOperacion";

        }

        //---------METODOS VARIOS----------------

        private void removerControles()   //Eliminar los controles que heredé pero que no los voy a usar.
        {
            this.Controls.Remove(this.lblPrecioCosto);
            this.Controls.Remove(this.txtPrecioCosto);
            this.Controls.Remove(this.lblPrecioVenta);
            this.Controls.Remove(this.txtPrecioVenta);
            this.Controls.Remove(this.lblStockActual);
            this.Controls.Remove(this.txtStockActual);
            this.Controls.Remove(this.lblCantMinima);
            this.Controls.Remove(this.txtCantMinima);
            this.Controls.Remove(this.btnAgregar);
            this.Controls.Remove(this.btnEditar);
            this.Controls.Remove(this.lblEditar);
            this.Controls.Remove(this.lblAgregar);


            this.Controls.Remove(this.lblErrorPCosto);
            this.Controls.Remove(this.lblErrorPVenta);
            this.Controls.Remove(this.lblErrorStockActual);
            this.Controls.Remove(this.lblErrorCantMin);
        }

        
        //Redefinido del padre
        protected override void actualizarResgProductos() //Se refresca el arrayList resgProductos
        {
            try
            {
                //(ALE) HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //ProductosTa.FillByProductos1(centerQuimDs,...);
                productosTa.Fill(centerQuimDs.Productos);

                resgProductos.Clear(); //Se vacia resgProductos (ArrayList)

                foreach (DataRow row in centerQuimDs.Productos) //Se recorre todas las filas  del centerQuimDs.Productos y se cargan los productos al ArrayList
                {
                    if ((row[6].ToString() == "D") & (Convert.ToDouble(row[9]) > 0))  //EN ESTE CASO A DIFERENCIA DEL PADRE SOLO SE AGREGAN LOS PRODUCTOS DISUELTOS VENDIDOS POR CANTIDAD
                    {
                        resgProductos.Add(new Producto(Convert.ToString(row[0]), Convert.ToString(row[1])));
                    }
                    
                }

                refrescarResgProductos = false;

            }
            catch (IndexOutOfRangeException)
            {
                //si llega a ocurrir esta excepcion no se tiene en cuenta. Podría no haber productos cargados y lanzaría esta excepción.

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
       
        }

        protected override void eventoBusCodigo()  //Se encapsula en un método capturado de evento cuando se presiona Enter sobre el txtCodBarra en estado de busqueda o click en btnBusCodBarra.
        {

            //no hace falta que pregunte si txtCodBarra es blanco, ya que por la forma de filtrar no encontrará nada igual.                                

            if (refrescarResgProductos)   //si es necesario actualizar el resgProductos se lo hace sino no
            {
                ejecutarHiloActualizarResgProductos();  //ejecuta el hilo que actualiza el ResgProductos
            }

            filtrarCodigoBarra();


            if (lstProductosCodBarra.Items.Count == 0)  //el filtro no obtuvo coincidencias.
            {
                //Se informa que no se encontró nada 
                MessageBox.Show("Su consulta no ha arrojado resultados.", "INFORME", MessageBoxButtons.OK, MessageBoxIcon.Information);

                deshacerCambios(); //coloca el estado de la ultima busqueda exitosa de un producto.

                //Como no encontró nada se deja en este estado.
                this.estEsperandoOperacion();
            }
            else
            {
                if (lstProductosCodBarra.Items.Count == 1)   //solo se encontró una sola coincidencia. No es necesario mostrar el lstProductosCodBarra. Directamente se muestra el producto.
                {
                    this.estadoDelFormulario = "Buscando";  //Se coloca este estado ya que si encuentra algo, cargará el txtDescripcion y lanzará el evento TextChanged()

                    cargarProductoPorCodigo(lstProductosCodBarra.Items[0].ToString());  //busca producto con codigo de barra único (una coincidencia) encontrado en el oHiloFiltrarCodBarra y lo carga en los textBox.

                    estEsperandoOperacion(); //se deja en el estado necesario

                    resguardarProductoActual(); //Guarda los valores de los textBox luego de una busqueda exitosa.
                }
                else
                {
                    //si se obtuvo más de una coincidencia, solo se muestran éstas en lstProductosCodBarra, y espera a que el usuario seleccione una.

                    lstProductosCodBarra.Visible = true;
                    lstProductosCodBarra.Enabled = true;

                    //lstProductosCodBarra.Focus(); //se deja el foco en el dgvProductosCodBarra para que elija alguna coincidencia.

                    //lstProductosCodBarra.SelectedIndex=0;  //se deja seleccionado el primer items.
                }

            }

        }

        
        //redefinido del padre.
        protected override void cargarProductoPorCodigo(string unaDescripción) //busca producto con codigo de barra único (una coincidencia) encontrado en el oHiloFiltrarCodBarra y lo carga en los textBox.
        {
            try
            {
                //(ALE)HACER EL FILL O COMO LO LLAMES ACA ABAJO
                //ProductosTa.FillByProductos1(centerQuimDs,unCodBarra);
                productosTa.FillByNombre(centerQuimDs.Productos, unaDescripción);

                //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada. 
                txtCodBarra.Text = centerQuimDs.Productos[0].codProducto;
                txtDescripcion.Text = centerQuimDs.Productos[0].descripcion;
                
                //..FALTAN LOS OTROS. ACORDATE QUE ESTE ES EL DE CAJERO, TIENE POCOS CONTROLES.

            }
            catch (IndexOutOfRangeException)
            {

            }
            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //Si llega a ocurrir algún error grave se cierra el formulario 
                this.Close();
            }
        }


        //redefinido del padre
        protected override void cargarProductoPorDescripcion(string unaDescripcion)  //busca el producto por descripción en la base de datos y lo carga en los textbox.
        {
            //(ALE) HACER EL FILL O COMO LO LLAMES ACA ABAJO
            productosTa.FillByNombre(centerQuimDs.Productos, unaDescripcion);

            //ARREGLAR ESTO. Se rellena los textBox con la consulta encontrada. 
            txtCodBarra.Text = centerQuimDs.Productos[0].codProducto;
            txtDescripcion.Text = centerQuimDs.Productos[0].descripcion;
            //..
            //...
            //..FALTAN LOS OTROS. ACORDATE QUE ESTE ES EL DE CAJERO, TIENE POCOS CONTROLES.

        }
        
        
        //redefinido del padre.
        protected override void resguardarProductoActual() //Guarda los valores de los textBox en array resgProductoActual, luego de una busqueda exitosa.
        {
            resgProductoActual[0] = txtCodBarra.Text;
            resgProductoActual[1] = txtDescripcion.Text;
            
        }

        //Redefinido del padre
        protected override void procesar() //se encapsulo en un método para usar cuando se presiona Enter con los textBox
        {
            if (formularioValido())
            {
                try
                {
                    incrementarStockDisuelto();

                }
                catch (IndexOutOfRangeException)
                {
                    //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                    MessageBox.Show("Debe seleccionar un producto disuelto para agregar a la gondola", "PRODUCTO DISUELTO NO INGRESADO", MessageBoxButtons.OK, MessageBoxIcon.Information);

                }
                catch (Exception ex)
                {
                    //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                    MessageBox.Show("La conexión a la base de datos no fué exitosa.\n\n Comuniquese con su desarrollador para solucionar el problema.\n\n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    //Si llega a ocurrir algún error en estado agregar 
                    this.Close();
                }

            }
            else
            {
                informarExistenciaError();
            }

            
        }

        private string obtenerFechaActual()  //Dato necesario para el alta de venta
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getFechaActual();
        }

        private void incrementarStockDisuelto()  //incrementa el stock del producto disuelto que se ha incrementado en cantidad.
        {
            DialogResult result = MessageBox.Show("¿Esta seguro que desea agregar: " + txtCantidad.Text + ", unidades, al producto con la siguiente descripción:? \n\nCodigo: " + resgProductoActual[0] + ", - Descripción: " + resgProductoActual[1], "CONFIRMACION ALTA DE UNIDADES DISUELTAS", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (result == DialogResult.Yes)
            {

                //FIJATE SI ESTÁ TODO BIEN. QUE COINCIDA CON TU CONSULTA
                productosTa.FillByNombre(centerQuimDs.Productos, resgProductoActual[1]);  //el argumento corresponde con la descripcion actual del producto a actualizar.
                centerQuimDs.Productos[0].stockActual = centerQuimDs.Productos[0].stockActual + Convert.ToDouble(txtCantidad.Text.Trim());
                productosTa.Update(centerQuimDs.Productos);

                movimientoProductoDisueltos (centerQuimDs .Productos [0].codProducto ,centerQuimDs .Productos [0].descripcion ,Convert.ToDouble(txtCantidad.Text.Trim()));

                resguardarProductoActual(); //Se resguarda el producto actual editado correctamente.

                decrementarStockBase(centerQuimDs.Productos[0].baseDescripcion, centerQuimDs.Productos[0].porcentaje, centerQuimDs.Productos[0].litrosEnvase); //se decrementa el porcentaje de monto de base del producto disuelto
                
                estEsperandoOperacion(); //Luego de insertar un usuario se vuelve al estado esperando operación. Para que pueda editarlo o eliminarlo rapidamente.

                //Se muestra un mje de confirmación.
                MessageBox.Show("Producto se ha ingresado con exito!!!", "AVISO", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }
        }

        private void decrementarStockBase(string unaBase, double unPorcentaje, double unLitroEnvase)
        {
            productosTa.FillByNombre(centerQuimDs.Productos, unaBase);  //el argumento corresponde con la descripcion actual del producto a actualizar.

            Double multiplicadorPorcentual = Math.Round((unPorcentaje / 100), 2);  //si el porcentaje era 3, el multiplicador queda: 0,03.

            Double cantidadDecrementar = Math.Round((Convert.ToDouble(txtCantidad.Text) * (unLitroEnvase) * multiplicadorPorcentual),3);

            centerQuimDs.Productos[0].stockActual = centerQuimDs.Productos[0].stockActual - cantidadDecrementar;
            
            productosTa.Update(centerQuimDs.Productos);

            movimientosBase(centerQuimDs.Productos[0].codProducto, centerQuimDs.Productos[0].descripcion, cantidadDecrementar);

        }

        
        //redefinido del padre
        protected override bool formularioValido()  
        {
            validarCantidad();

            if ((errorProvider1.GetError(txtCantidad) == ""))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void validarCantidad()
        {
            if (txtCantidad.Text.Trim() == "")
            {
                errorProvider1.SetError(txtCantidad, "Cantidad: el campo se encuentra vacio\n\n");
            }
            else
            {
                errorProvider1.SetError(txtCantidad, new ValidarDatos().ValidarNaturalesPositivos("Cantidad:", txtCantidad.Text));
            }
        }

        private void movimientoProductoDisueltos(string codigo, string nombre, double cantidad)
        {
            movimientosTa.InsertQueryMovimientosxProducto(codigo, nombre, Convert.ToDateTime(obtenerFechaActual()), "A", "Alta Disuelto", Convert.ToDecimal(cantidad));
        }

        private void movimientosBase(string codigo, string nombre, double cantidad)
        {
            movimientosTa.InsertQueryMovimientosxProducto(codigo, nombre, Convert.ToDateTime(obtenerFechaActual()), "B", "Baja por Disolución", Convert.ToDecimal(cantidad));
        }

        
        private void txtCantidad_KeyDown(object sender, KeyEventArgs e) //metodo capturador del evento enter sobre el txtCantidad. Si se presiona Intro se procesa.
        {
            if (e.KeyCode == Keys.Enter)
            {
                procesar();
            }

        }


    }
}
